﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace SAHM
{
    public class AnalyticsFilter:MemoryStream
    {
        private Stream _originalOutput = null;
        private StringBuilder _response = null;

        //private Regex _tagToReach = null;
        
        private List<AnalyticsCode> _codesToInject;
        
        private Regex _endOfPage = new Regex("</html>", RegexOptions.Compiled);

        

        public AnalyticsFilter(Stream originalOutput)
        {
            _originalOutput = originalOutput;
            _response = new StringBuilder();
            _codesToInject = new List<AnalyticsCode>();
            
            if (Config.IsGoogleEnabled)
            {
                string code = string.Format(AnalyticsScripts.google, Config.GoogleConfig.Code);
                _codesToInject.Add(new AnalyticsCode(AnalyticsTagsToReach.google, code));
            }
            if (Config.IsPiwikEnabled)
            {
                string code = string.Format(AnalyticsScripts.piwki, Config.PiwikConfig.Server,Config.PiwikConfig.SiteID);
                _codesToInject.Add(new AnalyticsCode(AnalyticsTagsToReach.piwik, code));
            }
            if (Config.IsUserVoiceEnabled)
            {
                string code = string.Format(AnalyticsScripts.uservoice, Config.UserVoiceConfig.SubDomain,
                    Config.UserVoiceConfig.ForumID, Config.UserVoiceConfig.Alignment, Config.UserVoiceConfig.BackgroundColor,
                    Config.UserVoiceConfig.TextColor, Config.UserVoiceConfig.HoverColor, Config.UserVoiceConfig.Language);
                _codesToInject.Add(new AnalyticsCode(AnalyticsTagsToReach.uservoice, code));
            }
            if (Config.IsOwaEnabled)
            {

                string code = string.Format(AnalyticsScripts.owa, Config.OwaConfig.Server, Config.OwaConfig.SiteID);
                _codesToInject.Add(new AnalyticsCode(AnalyticsTagsToReach.owa, code));
            }
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            // if no tracking is enabled
            if ((!Config.IsAnyTrackingSystemEnabled) || (_codesToInject == null))
            {
                _originalOutput.Write(buffer, offset, count);
                return;
            }
         

            // add code to response
            _response.Append(UTF8Encoding.UTF8.GetString(buffer));
            // gotcha : be sure that the all page is loaded before replacing, otherwise you may be replace twice ..
            if (_endOfPage.IsMatch(_response.ToString()))
            {

                string newOutput = string.Empty;
                foreach (AnalyticsCode acode in _codesToInject)
                {
                    if (string.IsNullOrEmpty(newOutput))// 1st loop
                    {
                        newOutput = acode.TagToReach.Replace(_response.ToString(), acode.CodeToInject);
                    }
                    else 
                    {
                        newOutput = acode.TagToReach.Replace(newOutput, acode.CodeToInject);
                    }
                }
               
                if (string.Compare(newOutput, string.Empty) != 0)
                {
                    byte[] newBuffer = UTF8Encoding.UTF8.GetBytes(newOutput);
                    _originalOutput.Write(newBuffer, 0, newBuffer.Length);
                }  
            }
        }
    }
}
